﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
using System.Linq;
using System.Management.Instrumentation;
using System.Web;

namespace Beryl.OrderControllers.DataStructural
{
    public class mOrderStructural
    {
        private static mOrderStructural instance = null;
        private static readonly object uniqueLock = new object();
        public static mOrderStructural Instance
        {
            get
            {
                lock (uniqueLock)
                {
                    if (instance == null)
                    {
                        instance = new mOrderStructural();
                    }
                }
                return instance;
            }
        }
        public mOrderStructural() { }

        #region 数据结构化
        /**
 * @description 格式化生产订单
 * @param {Array} cSOrds 生产订单数据
 * @returns {Object} 
 */
        public Dictionary<string, DataRow> getPOrderObj(DataRow[] PlanOrders)
        {
            var ordersObj = new Dictionary<string, DataRow>();
            try
            {
                for (int i = 0; i < PlanOrders.Length; i++)
                {
                    string cPOrderNo = PlanOrders[i]["cPOrderNo"].ToString();
                    if (!ordersObj.ContainsKey(cPOrderNo))
                    {
                        ordersObj.Add(cPOrderNo, null);
                    }
                    ordersObj[cPOrderNo] = PlanOrders[i];
                }
            }
            catch (Exception)
            {
                return null;
            }
            return ordersObj;
        }


        //获取重工单
        public Dictionary<string, Dictionary<string, List<DataRow>>> getReworkObj(DataRow[] rework)
        {
            var reworkObj = new Dictionary<string, Dictionary<string, List<DataRow>>>();
            Dictionary<string, List<DataRow>> keys = new Dictionary<string, List<DataRow>>();
            for (int i = 0; i < rework.Length; i++)
            {
                string cSONo = rework[i]["cSONo"].ToString();
                string cPRoutingId = rework[i]["cPRoutingId"].ToString();
                if (!reworkObj.ContainsKey(cSONo))
                {
                    reworkObj.Add(cSONo, new Dictionary<string, List<DataRow>>());
                    reworkObj[cSONo].Add(cPRoutingId, new List<DataRow>());
                    reworkObj[cSONo][cPRoutingId].Add(rework[i]);
                }
                else
                {
                    reworkObj[cSONo][cPRoutingId].Add(rework[i]);
                }
            }
            return reworkObj;
        }

        /**
 * 工艺路径结构化
 * @param {Array} Routing 产品工艺路径
 */
        public Dictionary<string, Dictionary<string, DataRow>> getRoutingObj(DataRow[] Routing)
        {
            Dictionary<string, Dictionary<string, DataRow>> RoutingObj = new Dictionary<string, Dictionary<string, DataRow>>();
            Dictionary<string, DataRow> keys = new Dictionary<string, DataRow>();
            for (int i = 0; i < Routing.Length; i++)
            {
                string cMatNo = Routing[i]["cMatNo"].ToString();
                string cOperationNo = Routing[i]["cOperationNo"].ToString();
                if (!RoutingObj.ContainsKey(cMatNo))
                {
                    RoutingObj.Add(cMatNo, null);
                    keys = new Dictionary<string, DataRow>();
                }
                if (keys.ContainsKey(cOperationNo))
                {
                    continue;
                }
                keys.Add(cOperationNo, Routing[i]);
                RoutingObj[cMatNo] = keys;
            }
            return RoutingObj;
        }

        /**
 * @description 工序、资源组、资源结构化
 * @param {Array} Resource 资源
 */
        public Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>> getResObj(DataRow[] Resource)
        {
            Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>> ResObj = new Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>();
            for (int i = 0; i < Resource.Length; i++)
            {
                string cOperationNo = Resource[i]["cOperationNo"].ToString();
                string cResGroupNo = Resource[i]["cResGroupNo"].ToString();
                string cResNo = Resource[i]["cResourceNo"].ToString();
                if (!ResObj.ContainsKey(cOperationNo))
                {
                    ResObj.Add(cOperationNo, new Dictionary<string, Dictionary<string, DataRow>>());
                }
                if (!ResObj[cOperationNo].ContainsKey(cResGroupNo))
                {
                    ResObj[cOperationNo].Add(cResGroupNo, new Dictionary<string, DataRow>());
                }
                if (!ResObj[cOperationNo][cResGroupNo].ContainsKey(cResNo))
                {
                    ResObj[cOperationNo][cResGroupNo].Add(cResNo, null);
                }
                ResObj[cOperationNo][cResGroupNo][cResNo] = Resource[i];
            }
            return ResObj;
        }

        /**
 * @description 资源结构化
 * @param {Array} Resource 资源
 */
        public Dictionary<string, DataRow> getResObj2(DataRow[] Resource)
        {
            Dictionary<string, DataRow> ResObj = new Dictionary<string, DataRow>();
            for (int i = 0; i < Resource.Length; i++)
            {
                string cResNo = Resource[i]["cResourceNo"].ToString();
                if (!ResObj.ContainsKey(cResNo))
                {
                    ResObj.Add(cResNo, null);
                }
                ResObj[cResNo] = Resource[i];
            }
            return ResObj;
        }

        public Dictionary<string, DataRow> getResGroup(DataRow[] resGroup)
        {
            Dictionary<string, DataRow> resGroupObj = new Dictionary<string, DataRow>();
            for (int i = 0; i < resGroup.Length; i++)
            {
                string resGroupNo = resGroup[i]["cResGroupNo"].ToString();
                if (!resGroupObj.ContainsKey(resGroupNo))
                {
                    resGroupObj.Add(resGroupNo, null);
                }
                resGroupObj[resGroupNo] = resGroup[i];
            }
            return resGroupObj;
        }

        /**
 * @description 资源日历数据格式化
 * @param {*} WorkCalendar 
 * @returns 
 */
        public Dictionary<string, Dictionary<string, Dictionary<string, string>>> getWorkCal(DataRow[] WorkCalendar)
        {
            Dictionary<string, Dictionary<string, Dictionary<string, string>>> WorkCalendarObj = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
            for (int i = 0; i < WorkCalendar.Length; i++)
            {
                //工序编号
                string cCalendarNo = WorkCalendar[i]["cCalendarNo"].ToString();
                //工作日期
                string WorkDay = WorkCalendar[i]["dCalendarDate"].ToString();
                //工作时常
                string workDuration = WorkCalendar[i]["dWorkTime"].ToString();
                if (!WorkCalendarObj.ContainsKey(cCalendarNo))
                {
                    WorkCalendarObj.Add(cCalendarNo, new Dictionary<string, Dictionary<string, string>>());
                }
                if (!WorkCalendarObj[cCalendarNo].ContainsKey(WorkDay))
                {
                    //一天的第1个班次
                    WorkCalendarObj[cCalendarNo].Add(WorkDay, new Dictionary<string, string>());
                    WorkCalendarObj[cCalendarNo][WorkDay].Add("cCalendarNo", cCalendarNo);
                    WorkCalendarObj[cCalendarNo][WorkDay].Add("dCalendarDate", WorkDay);
                    WorkCalendarObj[cCalendarNo][WorkDay].Add("dWorkTime", workDuration);
                    string cShift = WorkCalendar[i]["dStartTime1"].ToString() + "-" + WorkCalendar[i]["dEndTime1"].ToString() + "," + WorkCalendar[i]["dStartTime2"].ToString() + "-" + WorkCalendar[i]["dEndTime2"].ToString();
                    WorkCalendarObj[cCalendarNo][WorkDay].Add("cShift1", cShift);
                }
                else
                {
                    //一天的第2个班次
                    float fworkDuration = float.Parse(workDuration);
                    float oldworkDuration = float.Parse(WorkCalendarObj[cCalendarNo][WorkDay]["dWorkTime"]);
                    string total = (fworkDuration + oldworkDuration).ToString();
                    WorkCalendarObj[cCalendarNo][WorkDay]["dWorkTime"] = total;
                    string cShift = WorkCalendar[i]["dStartTime1"].ToString() + "-" + WorkCalendar[i]["dEndTime1"].ToString() + "," + WorkCalendar[i]["dStartTime2"].ToString() + "-" + WorkCalendar[i]["dEndTime2"].ToString();
                    WorkCalendarObj[cCalendarNo][WorkDay].Add("cShift2", cShift);
                }
            }
            return WorkCalendarObj;
        }

        /**
 * @description 工序日历数据格式化
 * @param {*} WorkCalendar 
 * @returns 
 */
        public Dictionary<string, Dictionary<string, float>> getWorkCal2(DataRow[] WorkCalendar)
        {
            Dictionary<string, Dictionary<string, float>> WorkCalendarObj = new Dictionary<string, Dictionary<string, float>>();
            for (int i = 0; i < WorkCalendar.Length; i++)
            {
                //工序编号
                string cOperationNo = WorkCalendar[i]["cOperationNo"].ToString();
                //工作日期
                string WorkDay = WorkCalendar[i]["dCalendarDate"].ToString();
                if (!WorkCalendarObj.ContainsKey(cOperationNo))
                {
                    WorkCalendarObj.Add(cOperationNo, new Dictionary<string, float>());
                }
                if (!WorkCalendarObj[cOperationNo].ContainsKey(WorkDay))
                {
                    WorkCalendarObj[cOperationNo].Add(WorkDay, 0);
                }
                WorkCalendarObj[cOperationNo][WorkDay] += float.Parse(WorkCalendar[i]["dWorkTime"].ToString());
            }
            return WorkCalendarObj;
        }

        /**
 * @description 资源的产能数据格式化
 * @param {Array} Capacity 数据库基础数据
 * @returns {Object} ResCapObj 资源产能集
 */
        public Dictionary<string, Dictionary<string, DataRow>> getResCapObj(DataRow[] Capacity)
        {
            Dictionary<string, Dictionary<string, DataRow>> ResCapObj = new Dictionary<string, Dictionary<string, DataRow>>();
            for (int i = 0; i < Capacity.Length; i++)
            {
                // 资源编号
                string cResNo = Capacity[i]["cResourceNo"].ToString();
                // 拍别
                string dDiameter = Capacity[i]["dDiameter"].ToString();
                if (!ResCapObj.ContainsKey(cResNo))
                {
                    ResCapObj.Add(cResNo, new Dictionary<string, DataRow>());
                }
                if (!ResCapObj[cResNo].ContainsKey(dDiameter))
                {
                    ResCapObj[cResNo].Add(dDiameter, null);
                }
                ResCapObj[cResNo][dDiameter] = Capacity[i];
            }
            return ResCapObj;
        }

        /**
 * @description 现存主计划数据格式化
 */
        public Dictionary<string, DataRow> getMainPlan(DataRow[] mainPlan)
        {
            Dictionary<string, DataRow> mainPlanObj = new Dictionary<string, DataRow>();
            for (int i = 0; i < mainPlan.Length; i++)
            {
                string cPOrderNo = mainPlan[i]["cPOrderNo"].ToString();
                if (!mainPlanObj.ContainsKey(cPOrderNo))
                {
                    mainPlanObj.Add(cPOrderNo, null);
                }
                mainPlanObj[cPOrderNo] = mainPlan[i];
            }
            return mainPlanObj;
        }

        /**
 * @description 生成BOM
 * @param {Array} ManuBOM 数据库bom
 */
        public Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>> getBOM(DataRow[] ManuBOM,out Dictionary<string,Dictionary<string,DataRow>> outBom)
        {
            Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>> BomObj = new Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>>();
            Dictionary<string, Dictionary<string, DataRow>> outBomObj = new Dictionary<string, Dictionary<string, DataRow>>();
            try
            {
                DataTable dt = CommonMethod.Instance.ToDataTable(ManuBOM);
                dt.Columns.Add("UnitUsage", typeof(string));

                DataRow[] dataRows = dt.Select("1 = 1");
                for (int i = 0; i < dataRows.Length; i++)
                {
                    // 用量分子
                    string dQty = dataRows[i]["dQty"].ToString();
                    // 母件
                    string MatNo = dataRows[i]["cMatNo"].ToString();
                    // 指令类型
                    string InOutType = dataRows[i]["cInOutType"].ToString();
                    // 用量分母
                    string MeasureUnit = dataRows[i]["dMeasureUnit"].ToString();
                    // 子件
                    string ResNo = dataRows[i]["cMatandResNo"].ToString();
                    // 工序编号
                    string OperationNo = dataRows[i]["cOperationNo"].ToString();
                    // 子件类型
                    string ResType = dataRows[i]["cMatandResType"].ToString();
                    // 子件名称
                    string ResName = dataRows[i]["cMatandResName"].ToString();

                    if (dQty == "" || MeasureUnit == "")
                    {
                        dataRows[i]["UnitUsage"] = "0";
                    }
                    else
                    {
                        dataRows[i]["UnitUsage"] = float.Parse(dQty) / float.Parse(MeasureUnit);
                    }

                    if (InOutType == "output")
                    {
                        if(!outBomObj.ContainsKey(MatNo))
                        {
                            outBomObj.Add(MatNo, new Dictionary<string, DataRow>());
                        }
                        if (!outBomObj[MatNo].ContainsKey(InOutType))
                        {
                            outBomObj[MatNo].Add(InOutType, null);
                        }
                        outBomObj[MatNo][InOutType] = ManuBOM[i];
                    }
                    else if (InOutType == "input")
                    {
                        if (!BomObj.ContainsKey(MatNo))
                        {
                            BomObj.Add(MatNo, new Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>());
                        }
                        if (!BomObj[MatNo].ContainsKey(InOutType))
                        {
                            BomObj[MatNo].Add(InOutType, new Dictionary<string, Dictionary<string, DataRow>>());
                        }

                        if (!BomObj[MatNo][InOutType].ContainsKey(OperationNo))
                        {
                            BomObj[MatNo][InOutType].Add(OperationNo, new Dictionary<string, DataRow>());
                        }
                        if (BomObj[MatNo][InOutType][OperationNo].ContainsKey(ResNo))
                        {
                            BomObj[MatNo][InOutType][OperationNo][ResNo] = dataRows[i];
                        }
                        else
                        {
                            BomObj[MatNo][InOutType][OperationNo].Add(ResNo, dataRows[i]);
                        }
                    }
                    else
                    {
                        throw new Exception("存在非法的指令类型");
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            outBom = outBomObj;
            return BomObj;
        }

        /**
 * @description 物料主数据格式化
 * @param {Array} MatData 物料数据
 */
        public Dictionary<string, DataRow> getMatData(DataRow[] MatData)
        {
            Dictionary<string, DataRow> MatDataObj = new Dictionary<string, DataRow>();
            try
            {
                for (int i = 0; i < MatData.Length; i++)
                {
                    //物料名称
                    string cMatNo = MatData[i]["cMatNo"].ToString();
                    if (MatDataObj.ContainsKey(cMatNo))
                    {
                        // throw new Exception("物料数据中存在多个相同物料");
                    }
                    else
                    {
                        MatDataObj.Add(cMatNo, MatData[i]);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return MatDataObj;
        }

        /**
 * @description 设备维保计划结构化
 * @param {*} maintainPlan 
 * @returns 
 */
        public Dictionary<string, Dictionary<string, float>> getMaintainObj(DataRow[] maintainPlan, Dictionary<string, DataRow> ResObj2,
            Dictionary<string, Dictionary<string, Dictionary<string, string>>> CalendarObj)
        {
            Dictionary<string, Dictionary<string, float>> MatainPlanObj = new Dictionary<string, Dictionary<string, float>>();
            try
            {
                foreach (var ele in maintainPlan)
                {
                    string resourceNo = ele["cDeviceNo"].ToString(); // 维保的设备号
                    string calendarNo = ResObj2[resourceNo]["cCalendarNo"].ToString(); // 维保设备的日历
                    if (!MatainPlanObj.ContainsKey(resourceNo))
                    {
                        MatainPlanObj.Add(resourceNo, new Dictionary<string, float>());
                    }
                    if (CalendarObj.ContainsKey(calendarNo))
                    {
                        //考虑维保时间跨天的情况
                        int deta = CommonMethod.Instance.diffDate(ele["dEndTime"].ToString(), ele["dStartTime"].ToString());
                        // 若跨天
                        if (deta > 0)
                        {
                            for (int i = 0; i < deta; i++)
                            {
                                float repairDuration = 0;//维修时长
                                string repairDate = CommonMethod.Instance.addDate(ele["dStartTime"].ToString(), i, 1);
                                //班次的上下班时间
                                string shift1 = CalendarObj[calendarNo][repairDate]["cShift1"].ToString(); //'08:00-11:45,12:45-20:00'
                                string shift2 = CalendarObj[calendarNo][repairDate]["cShift2"].ToString(); //'20:00-01:00,02:00-08:00'
                                Dictionary<string, string> shiftTime = CommonMethod.Instance.formatShift(repairDate, shift1, shift2);

                                if (i == 0)
                                {
                                    //判断维修开始时间包含在哪个时间段内
                                    if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st1"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et1"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"].ToString());
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"].ToString());
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"].ToString());
                                        repairDuration = t1 + t2 + t3 + t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) > DateTime.Parse(shiftTime["s1_et1"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) < DateTime.Parse(shiftTime["s1_st2"]))
                                    {
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st1"].ToString());
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"].ToString());
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"].ToString());
                                        repairDuration = t2 + t3 + t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                                    {
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"].ToString());
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"].ToString());
                                        repairDuration = t2 + t3 + t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) > DateTime.Parse(shiftTime["s1_et2"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) < DateTime.Parse(shiftTime["s2_st1"]))
                                    {
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                        repairDuration = t3 + t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st1"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et1"]))
                                    {
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], ele["dStartTime"].ToString());
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"].ToString());
                                        repairDuration = t3 + t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) > DateTime.Parse(shiftTime["s2_et1"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) < DateTime.Parse(shiftTime["s2_st2"]))
                                    {
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                        repairDuration = t4;
                                    }
                                    else if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st2"]) &&
                                        DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et2"]))
                                    {
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], ele["dStartTime"].ToString());
                                        repairDuration = t4;
                                    }
                                    else
                                    {
                                        repairDuration = 0;
                                    }
                                }
                                else if (i < deta)
                                {
                                    //全天维修
                                    repairDuration = float.Parse(CalendarObj[calendarNo][repairDate]["dWorkTime"]);
                                }
                                else
                                {
                                    //判断维修结束时间包含在哪个时间段内
                                    if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st1"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et1"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s1_st1"]);
                                        repairDuration = t1;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et1"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s1_st2"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        repairDuration = t1;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s1_st2"]);
                                        repairDuration = t1 + t2;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et2"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st1"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                        repairDuration = t1 + t2;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st1"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et1"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                        int t3 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st1"].ToString());
                                        repairDuration = t1 + t2 + t3;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s2_et1"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st2"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                        repairDuration = t1 + t2 + t3;
                                    }
                                    else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st2"]) &&
                                        DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et2"]))
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                        int t4 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st2"]);
                                        repairDuration = t1 + t2 + t3 + t4;
                                    }
                                    else
                                    {
                                        int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                        int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                        int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                        int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                        repairDuration = t1 + t2 + t3 + t4;
                                    }
                                }
                                MatainPlanObj[resourceNo][repairDate] = repairDuration;
                            }
                        }
                        else
                        {
                            // 若不跨天
                            DateTime da = DateTime.Parse(ele["dStartTime"].ToString());
                            string repairDate = da.ToString("yyyy-MM-dd");
                            if (!MatainPlanObj[resourceNo].ContainsKey(repairDate))
                            {
                                MatainPlanObj[resourceNo].Add(repairDate, 0);
                            }
                            string shift1 = CalendarObj[calendarNo][repairDate]["cShift1"]; //'08:00-11:45,12:45-20:00'
                            string shift2 = CalendarObj[calendarNo][repairDate]["cShift2"]; //'20:00-01:00,02:00-08:00'
                            Dictionary<string, string> shiftTime = CommonMethod.Instance.formatShift(repairDate, shift1, shift2);

                            //默认维修开始时间只在白班
                            if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st1"]) &&
                                DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et1"]))
                            {
                                if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), ele["dStartTime"].ToString());
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s1_st2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s1_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t3 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s2_et1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t4 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3 + t4;
                                }
                                else
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et1"], shiftTime["s1_st1"]);
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t4 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3 + t4;
                                }
                            }
                            else if (DateTime.Parse(ele["dStartTime"].ToString()) > DateTime.Parse(shiftTime["s1_et1"]) &&
                                DateTime.Parse(ele["dStartTime"].ToString()) < DateTime.Parse(shiftTime["s1_st2"]))
                            {
                                if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s1_st2"]))
                                {
                                    MatainPlanObj[resourceNo][repairDate] = 0;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s1_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t2 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s2_et1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t3 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                                else
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], shiftTime["s1_st2"]);
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                            }
                            else if (DateTime.Parse(ele["dStartTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                DateTime.Parse(ele["dStartTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                            {
                                if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s1_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s1_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), ele["dStartTime"].ToString());
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s1_et2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                    MatainPlanObj[resourceNo][repairDate] = t1;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et1"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) > DateTime.Parse(shiftTime["s2_et1"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) < DateTime.Parse(shiftTime["s2_st2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2;
                                }
                                else if (DateTime.Parse(ele["dEndTime"].ToString()) >= DateTime.Parse(shiftTime["s2_st2"]) &&
                                    DateTime.Parse(ele["dEndTime"].ToString()) <= DateTime.Parse(shiftTime["s2_et2"]))
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t3 = CommonMethod.Instance.diffHour(ele["dEndTime"].ToString(), shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                                else
                                {
                                    int t1 = CommonMethod.Instance.diffHour(shiftTime["s1_et2"], ele["dStartTime"].ToString());
                                    int t2 = CommonMethod.Instance.diffHour(shiftTime["s2_et1"], shiftTime["s2_st1"]);
                                    int t3 = CommonMethod.Instance.diffHour(shiftTime["s2_et2"], shiftTime["s2_st2"]);
                                    MatainPlanObj[resourceNo][repairDate] = t1 + t2 + t3;
                                }
                            }
                            else
                            {
                                MatainPlanObj[resourceNo][repairDate] = 0;
                            }
                        }
                    }
                    else
                    {
                        // console.warn(`该维修设备${resourceNo}不占用产能。`);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return MatainPlanObj;
        }

        /**
 * @description 计算当前可用资源组的产能1，扣除维保计划的产能
 * @param {*} ResObj  资源组 & 资源目前的状态
 * @param {*} ResCapObj  资源的产能
 * @param {*} CalendarObj 日历
 * @param {*} MatainPlanObj 资源维保计划
 * @param {return} 资源组每日的产能
 */
        public Dictionary<string, Dictionary<string, Dictionary<string, float>>> getResCapacity1(Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>> ResObj,
            Dictionary<string, Dictionary<string, Dictionary<string, string>>> CalendarObj, Dictionary<string, Dictionary<string, DataRow>> ResCapObj,
            Dictionary<string, Dictionary<string, float>> MatainPlanObj)
        {
            Dictionary<string, Dictionary<string, Dictionary<string, float>>> ResDayCap = new Dictionary<string, Dictionary<string, Dictionary<string, float>>>();
            try
            {
                // 遍历工序
                foreach (var perationNo in ResObj.Keys)
                {
                    // 遍历资源组
                    foreach (var resGroup in ResObj[perationNo].Keys)
                    {
                        // 遍历资源
                        foreach (var resource in ResObj[perationNo][resGroup].Keys)
                        {
                            string meterType = ResObj[perationNo][resGroup][resource]["cMeterType"].ToString();
                            if (meterType.Contains("."))
                            {
                                meterType = meterType + "0";
                            }
                            else
                            {
                                meterType = meterType + ".00";
                            }
                            string calendarNo = ResObj[perationNo][resGroup][resource]["cCalendarNo"].ToString();
                            // 寻找资源的日历
                            if (CalendarObj.ContainsKey(calendarNo))
                            {
                                // 计算在该日历下每天的产能
                                foreach (var workDay in CalendarObj[calendarNo].Keys)
                                {
                                    //日工作时长 扣除维保计划中每日的维保时长
                                    float workTime = 0;
                                    if (MatainPlanObj != null && (MatainPlanObj.ContainsKey(resource) && MatainPlanObj[resource].ContainsKey(workDay)))
                                    {
                                        workTime = float.Parse(CalendarObj[calendarNo][workDay]["dWorkTime"]) - MatainPlanObj[resource][workDay];
                                    }
                                    else
                                    {
                                        workTime = float.Parse(CalendarObj[calendarNo][workDay]["dWorkTime"]);
                                    }
                                    //小时产能
                                    string hourlyCap = ResCapObj[resource][meterType]["dHourlyCapacity"].ToString();
                                    //产能系数
                                    string capacityRatio = ResCapObj[resource][meterType]["dCapacityRatio"].ToString();
                                    //日产能
                                    float dayCap = workTime * float.Parse(hourlyCap) * float.Parse(capacityRatio);
                                    dayCap = (float)Math.Round(dayCap, 2);
                                    if (!ResDayCap.ContainsKey(perationNo))
                                    {
                                        ResDayCap.Add(perationNo, new Dictionary<string, Dictionary<string, float>>());
                                    }
                                    if (!ResDayCap[perationNo].ContainsKey(resGroup))
                                    {
                                        ResDayCap[perationNo].Add(resGroup, new Dictionary<string, float>());
                                    }
                                    if (!ResDayCap[perationNo][resGroup].ContainsKey(workDay))
                                    {
                                        ResDayCap[perationNo][resGroup].Add(workDay, 0);
                                    }
                                    ResDayCap[perationNo][resGroup][workDay] += dayCap;
                                }
                            }
                            else
                            {
                                throw new Exception("资源" + resource + "没有配置日历");
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return ResDayCap;
        }

        /**
 * @description 在获得扣除了维保计划后的产能基础上，计算扣除现存主计划后的产能
 * @param {Object} resCap 扣除了维保计划后的每日产能
 * @param {Object} mainPlanObj 现存主计划
 * @param {Object} SOrderObj 当前需要做计划的销售订单
 */
        public Dictionary<string, Dictionary<string, Dictionary<string, float>>> getResCapacity2(Dictionary<string, Dictionary<string, Dictionary<string, float>>> resCap,
            Dictionary<string, DataRow> mainPlanObj, Dictionary<string, DataRow> SOrderObj)
        {
            try
            {
                string operationNo = "";
                if (resCap.Count == 1)
                {
                    foreach (var t in resCap.Keys)
                    {
                        operationNo = t;
                    }
                }
                else
                {
                    throw new Exception("resCap 存在多个operationNo");
                }
                foreach (var cPOrderNo in mainPlanObj.Keys)
                {
                    //当前要做计划的销售订单，不计入内
                    DataRow ele = mainPlanObj[cPOrderNo];
                    if (!SOrderObj.ContainsKey(ele["cPOrderNo"].ToString()))
                    {
                        string resGroupNo = ele["cResGroupNo"].ToString();
                        //若当天开工、当天结束
                        if (ele["cRgBegDate"].ToString() == ele["cRgEndDate"].ToString())
                        {
                            if (resCap.ContainsKey(operationNo) && resCap[operationNo].ContainsKey(resGroupNo))
                            {
                                if(resCap[operationNo].Count == 58)
                                {

                                }
                                if (ele["dQty"].ToString() == "")
                                {
                                    resCap[operationNo][resGroupNo][ele["cRgBegDate"].ToString()] -= 0;
                                }else
                                {
                                    if(!resCap[operationNo][resGroupNo].ContainsKey(ele["cRgBegDate"].ToString()))
                                    {
                                        continue;
                                    }else
                                    {
                                        resCap[operationNo][resGroupNo][ele["cRgBegDate"].ToString()] -= float.Parse(ele["dQty"].ToString());
                                    }
                                    
                                }
                                
                            }
                            else
                            {
                                //console.log(resGroupNo);
                                //return {resCode:"failed",resMsg:`资源组没有${resGroupNo}`,data:{}};
                                continue;
                            }
                        }
                        else
                        {
                            //若主计划中，钉卷工序的结束时间与开始时间不是同一天，说明订单的数量大于开始那天的剩余产能，则开始那天的剩余产能全部被占用，且订单数量做递
                            int diff = DateTime.Parse(ele["cRgEndDate"].ToString()).Day - DateTime.Parse(ele["cRgBegDate"].ToString()).Day;
                            float dQty = float.Parse(ele["dQty"].ToString()); //订单的数量
                            for (int i = 0; i <= diff; i++)
                            {
                                string date = CommonMethod.Instance.addDate(ele["cRgBegDate"].ToString(), i, 1);
                                if (i != diff)
                                {
                                    // if(!resCap[operationNo][resGroupNo].hasOwnProperty(date)){
                                    //     continue;
                                    // }
                                    //console.log(resGroupNo);

                                    //测试是否存在日期
                                    if (!resCap[operationNo][resGroupNo].ContainsKey(date))
                                    {
                                        dQty = 0; //扣掉当天的剩余产能
                                        resCap[operationNo][resGroupNo].Add(date, 0); //当天的剩余产能全部被占用
                                    }else
                                    {
                                        dQty -= resCap[operationNo][resGroupNo][date]; //扣掉当天的剩余产能
                                        resCap[operationNo][resGroupNo][date] = 0; //当天的剩余产能全部被占用
                                    }
                                }
                                else
                                {
                                    //测试是否存在日期
                                    if (!resCap[operationNo][resGroupNo].ContainsKey(date))
                                    {
                                        resCap[operationNo][resGroupNo].Add(date, 0);
                                    }else
                                    {
                                        resCap[operationNo][resGroupNo][date] -= dQty;
                                    }
                                    dQty = 0;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw e;
            }
            return resCap;
        }

        /**
 * @description 针对大批量订单，计算对应的配比需要的产能数据。根据资源组中，按照产能从大到小安排专机。
 * @param {*} ResGroupObj 所有资源组
 * @param {*} ResObj 当前的可用资源
 * @param {*} ResCapObj 资源的产能
 * @param {*} CalendarObj 工作日历
 * @param {return} 大批量订单每日安排生产的产能
 */

        public Dictionary<string, Dictionary<string, float>> getBigOrderCap(Dictionary<string, DataRow> ResGroupObj, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>> ResObj,
            Dictionary<string, Dictionary<string, DataRow>> ResCapObj, Dictionary<string, Dictionary<string, Dictionary<string, string>>> CalendarObj,
            Dictionary<string, Dictionary<string, float>> MatainPlanObj)
        {
            Dictionary<string, Dictionary<string, float>> bigOrderCap = new Dictionary<string, Dictionary<string, float>>();
            try
            {
                //遍历工序
                foreach (var cOperationNo in ResObj.Keys)
                {
                    //遍历资源组
                    foreach (var cResGroupNo in ResObj[cOperationNo].Keys)
                    {
                        //获取资源组配比对应的资源使用数量
                        float dBigOrderResNum;
                        if (ResGroupObj.ContainsKey(cResGroupNo))
                        {
                            if (ResGroupObj[cResGroupNo]["dBigOrderResNum"].ToString() == "")
                            {
                                dBigOrderResNum = 0;
                            }
                            else
                            {
                                dBigOrderResNum = float.Parse(ResGroupObj[cResGroupNo]["dBigOrderResNum"].ToString());
                            }
                        }
                        else
                        {
                            dBigOrderResNum = 0;
                        }
                        int count = 0; //记录遍历资源的计数器
                        Dictionary<string, List<Dictionary<string, string>>> tempObj = new Dictionary<string, List<Dictionary<string, string>>>(); //存储临时数据
                        // 遍历资源 大批量订单的资源组中，选取产能最大的资源用于作为大批量订单的专机
                        foreach (var cResourceNo in ResObj[cOperationNo][cResGroupNo].Keys)
                        {
                            string cCalendarNo = ResObj[cOperationNo][cResGroupNo][cResourceNo]["cCalendarNo"].ToString();
                            string meterType = ResObj[cOperationNo][cResGroupNo][cResourceNo]["cMeterType"].ToString();
                            if(!meterType.Contains("."))
                            {
                                meterType = meterType + ".00";
                            }
                            else
                            {
                                meterType = meterType + "0";
                            }
                            // 寻找资源的日历
                            if (CalendarObj.ContainsKey(cCalendarNo))
                            {
                                // 计算在该日历下每天的产能
                                foreach (var workDay in CalendarObj[cCalendarNo].Keys)
                                {
                                    //日工作时长 扣除维保计划中每日的维保时长
                                    float workTime = 0;
                                    if (MatainPlanObj.ContainsKey(cResourceNo) && MatainPlanObj[cResourceNo].ContainsKey(workDay))
                                    {
                                        workTime = float.Parse(CalendarObj[cCalendarNo][workDay]["dWorkTime"].ToString()) - MatainPlanObj[cResourceNo][workDay];
                                    }
                                    else
                                    {
                                        workTime = float.Parse(CalendarObj[cCalendarNo][workDay]["dWorkTime"].ToString());
                                    }
                                    //小时产能
                                    string hourlyCap = ResCapObj[cResourceNo][meterType]["dHourlyCapacity"].ToString();
                                    //产能系数
                                    string capacityRatio = ResCapObj[cResourceNo][meterType]["dCapacityRatio"].ToString();
                                    //日产能
                                    float dayCap = workTime * float.Parse(hourlyCap) * float.Parse(capacityRatio);
                                    //选取产能较高的资源  资源按照日产能大小升序存在数组中
                                    if (!bigOrderCap.ContainsKey(cResGroupNo))
                                    {
                                        bigOrderCap.Add(cResGroupNo, new Dictionary<string, float>());
                                    }
                                    if (!bigOrderCap[cResGroupNo].ContainsKey(workDay))
                                    {
                                        bigOrderCap[cResGroupNo].Add(workDay, 0);
                                    }
                                    if (!tempObj.ContainsKey(workDay))
                                    {
                                        tempObj.Add(workDay, new List<Dictionary<string, string>>());
                                    }
                                    if (count < dBigOrderResNum)
                                    {
                                        Dictionary<string, string> obj = new Dictionary<string, string>
                                        {
                                            { "cResourceNo", cResourceNo },
                                            { "dDayCap", dayCap.ToString() }
                                        };
                                        tempObj[workDay].Add(obj);
                                        bigOrderCap[cResGroupNo][workDay] += dayCap;
                                    }
                                    else
                                    {
                                        if (tempObj[workDay].Count > 0)
                                        {
                                            // 按照资源的日产能升序排列
                                            tempObj[workDay].Sort((obj1, obj2) =>
                                            {
                                                return int.Parse(obj1["dDayCap"]) - int.Parse(obj2["dDayCap"]);
                                            });
                                            // 若当前资源的日产能 大于 已选用的最小产能，则取代之
                                            if (dayCap > float.Parse(tempObj[workDay][0]["dDayCap"].ToString()))
                                            {
                                                //减去产能最小的这个资源
                                                bigOrderCap[cResGroupNo][workDay] -= float.Parse(tempObj[workDay][0]["dDayCap"]);
                                                tempObj[workDay].RemoveAt(0);
                                                //增加当前的资源
                                                Dictionary<string, string> obj = new Dictionary<string, string>
                                                {
                                                   { "cResourceNo", cResourceNo },
                                                   { "dDayCap", dayCap.ToString() }
                                                };
                                                tempObj[workDay].Add(obj);
                                                bigOrderCap[cResGroupNo][workDay] += dayCap;
                                            }
                                        }
                                    }
                                }
                                count++;
                            }
                            else
                            {
                                throw new Exception("资源" + cResourceNo + "没有配置日历");
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return bigOrderCap;
        }

        /**
 * @description 根据主计划数据，计算钉卷工序资源组的最早可用日期
 * @param {Object} mainPlanObj2 主计划数据
 * @param {Object} SOrderObj 当前要计划的销售订单数据
 * @returns {Object} 
 */
        public Dictionary<string, string> getResGroupStartDate(Dictionary<string, DataRow> mainPlanObj, Dictionary<string, DataRow> SOrderObj)
        {
            Dictionary<string, string> resStartDateObj = new Dictionary<string, string>();
            try
            {
                foreach (var cPOrderNo in mainPlanObj.Keys)
                {
                    var ele = mainPlanObj[cPOrderNo];
                    //若当前销售订单已经做过主计划，则不重复做
                    if (!SOrderObj.ContainsKey(ele["cPOrderNo"].ToString()))
                    {
                        string resGroupNo = ele["cResGroupNo"].ToString();
                        //寻找某个资源组最新的cRgEndDate
                        if (!resStartDateObj.ContainsKey(resGroupNo))
                        {
                            resStartDateObj.Add(resGroupNo, null);
                            resStartDateObj[resGroupNo] = ele["cRgEndDate"].ToString();
                        }
                        else
                        {
                            if (DateTime.Parse(ele["cRgEndDate"].ToString()) > DateTime.Parse(resStartDateObj[resGroupNo]))
                            {
                                resStartDateObj[resGroupNo] = ele["cRgEndDate"].ToString();
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return resStartDateObj;
        }



        /**
         * 排主计划
 * @param {Object} BomObj bom对象
 * @param {Object} ResCapObj 资源产能
 * @param {Object} queryOrder 待询期订单
 * @param {Object} RoutingObj 工艺路径
 */
        public Dictionary<string, Dictionary<string, string>> getMainPlanCal(DataRow[] rule, DataRow[] sOrders, Dictionary<string, Dictionary<string, List<DataRow>>> reworkObj,
            Dictionary<string, Dictionary<string, DataRow>> RoutingObj, Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>> BomObj,
Dictionary<string, Dictionary<string, DataRow>> outBom, Dictionary<string, Dictionary<string, float>> OpeCalendarObj, Dictionary<string, string> resStartDateObj, Dictionary<string, Dictionary<string, Dictionary<string, float>>> resCap,
            Dictionary<string, Dictionary<string, float>> bigOrderCap, Dictionary<string, DataRow> MatDataObj)
        {
            Dictionary<string, Dictionary<string, string>> mainPlanRes = new Dictionary<string, Dictionary<string, string>>();
            try
            {
                DataTable dt = CommonMethod.Instance.ToDataTable(sOrders);
                dt.Columns.Add("dRealQty", typeof(string));
                dt.Columns.Add("dNetQty3", typeof(string));
                sOrders = dt.Select("1 = 1");

                string today = CommonMethod.Instance.getTime3();
                //划分大批次订单与普通订单
                List<DataRow> bigSOrders = new List<DataRow>(); //较大批次销售订单
                List<DataRow> genSOrders = new List<DataRow>(); //普通批次销售订单
                List<DataRow> notPlanSOrders = new List<DataRow>();//净需求为0销售订单
                float dBigOrderLimitNum = rule[0]["cIsActive"].ToString() == "1" ? float.Parse(rule[0]["cRuleValue"].ToString()) : 999999999; //大批次订单与普通订单的界限
                for (int i = 0; i < sOrders.Length; i++)
                {
                    if (sOrders[i]["dPlanQty"].ToString() != null)
                    {
                        if (float.Parse(sOrders[i]["dPlanQty"].ToString()) > 0)
                        {
                            sOrders[i]["dRealQty"] = sOrders[i]["dPlanQty"].ToString(); //便于后面计算，将有效的净需求数量统一成 dRealQty
                            if (float.Parse(sOrders[i]["dPlanQty"].ToString()) >= dBigOrderLimitNum)
                            {
                                bigSOrders.Add(sOrders[i]);
                            }
                            else
                            {
                                genSOrders.Add(sOrders[i]);
                            }
                        }
                        else
                        {
                            throw new Exception("制定主计划失败：生产订单" + sOrders[i]["cPOrderNo"].ToString() + "的净需求未计算！");
                        }
                    }
                }


                //大批次订单先占用产能，给大批量订单指定产能
                for (int i = 0; i < bigSOrders.Count; i++)
                {
                    string cPOrderNo = bigSOrders[i]["cPOrderNo"].ToString();
                    string cMatNo = bigSOrders[i]["cMatNo"].ToString();
                    string cSpecifucation = "";
                    if (MatDataObj.ContainsKey(cMatNo))
                    {
                        cSpecifucation = MatDataObj[cMatNo]["cSpecifucation"].ToString();
                    }
                    string dNetQty3 = bigSOrders[i]["dNetQty3"].ToString();
                    string dRealQty = bigSOrders[i]["dRealQty"].ToString();
                    string processEndDate = today; //订单的完工日期 默认是今日
                    string startDate = today;      //订单的开工日期 默认是今日
                    List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr = new List<Dictionary<string, Dictionary<string, DataRow>>>();
                    List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr1 = new List<Dictionary<string, Dictionary<string, DataRow>>>();
                    var childProductArr = getChildProduct(tmpArr,cMatNo, BomObj,RoutingObj, outBom); //找出成品对应的半成品子件，及对应的工序
                    var childProductArr2 = getReworkChildProduct(tmpArr1,cPOrderNo, cMatNo, reworkObj); //找出成品对应的半成品子件，及对应的工序
                    if(dNetQty3 != "")
                    {
                        childProductArr = childProductArr2;
                    }
                    //遍历半成品子件，及对应的工序
                    string childProduct = "";
                    string cOperationNo = "";
                    string cOperationName = "";
                    //遍历半成品子件，及对应的工序  
                    for (int j = 0; j < childProductArr.Count; j++)
                    {
                        foreach (var ret in childProductArr[j].Keys)
                        {
                            childProduct = ret;
                        }

                        //foreach(var ret in childProductArr[j][childProduct].Keys)
                        //{
                        //    cOperationNo = ret;
                        //}

                        float dTransferTimes = 0;

                        //遍历工序
                        foreach(var ret in childProductArr[j][childProduct].Values)
                        {
                            cOperationName = ret["cOperationName"].ToString(); //工序名称
                            cOperationNo = ret["cOperationNo"].ToString();
                            float dTransferTime = ret["dTransferTime"].ToString() != null ? float.Parse(ret["dTransferTime"].ToString()) : 1; //工序间的流转时间
                            //钉卷工序 计算钉卷工序的开完工日期
                            if(cOperationName.Contains("钉卷"))
                            {
                                string cCombination = ret["cCombination"].ToString(); //配比
                                if(cCombination == null)
                                {
                                    throw new Exception("请在ERP中维护" + cSpecifucation + "规格的BOM数据, 同步ERP数据后再重制定主计划！");
                                }
                                string cResGroup = "RG" + cCombination; //配比对应的资源组
                                //若当前有需要的资源组，则才进行计算，否则返回错误
                                if (resCap.ContainsKey(cOperationNo))
                                {
                                    if (resCap[cOperationNo].ContainsKey(cResGroup))
                                    {
                                        float tempQty = float.Parse(dRealQty);
                                        //获取资源组的最早可开工时间
                                        startDate = CommonMethod.Instance.addDate(today, 1, 1); //默认最早可开工日期是明天
                                        if (resStartDateObj.ContainsKey(cResGroup))
                                        {
                                            startDate = resStartDateObj[cResGroup]; //更新资源组的有效最早可开工日期
                                        }
                                        //若startDate这天有剩余产能，则有效，否则再更新startDate
                                        float count = 0;
                                        while (!resCap[cOperationNo][cResGroup].ContainsKey(startDate) || (resCap[cOperationNo][cResGroup].ContainsKey(startDate) && resCap[cOperationNo][cResGroup][startDate] <= 0))
                                        {
                                            startDate = CommonMethod.Instance.addDate(startDate, 1, 1);
                                            count++;
                                            if (count > 30)
                                            {
                                                if (resCap[cOperationNo][cResGroup].ContainsKey(startDate))
                                                {
                                                    //break;
                                                    //return {resCode:"failed",resMsg:`${cOperationName}工序资源组30天内无有效产能,资源组30天的产能被占用完，等待资源释放后该订单在做主计划。`,data:{}};
                                                }
                                                else
                                                {
                                                    break;
                                                    //return {resCode:"failed",resMsg:`${cOperationName}工序30天内没有配置日历。`,data:{}};
                                                }
                                            }
                                        }

                                        //记录开工日期
                                        if (!mainPlanRes.ContainsKey(cPOrderNo))
                                        {
                                            mainPlanRes.Add(cPOrderNo,new Dictionary<string, string>());
                                        }
                                        mainPlanRes[cPOrderNo].Add("cRgBegDate", "");
                                        mainPlanRes[cPOrderNo].Add("cBegProDate", "");
                                        mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                        mainPlanRes[cPOrderNo].Add("cResGroupNo", cResGroup);
                                        mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                        //扣减产能
                                        float diffDayCap;
                                        processEndDate = startDate;
                                        float count2 = 0;

                                        while (tempQty > 0)
                                        {
                                            if (bigOrderCap.ContainsKey(cResGroup))
                                            {
                                                if (bigOrderCap[cResGroup].ContainsKey(processEndDate))
                                                {
                                                    //因为每日优先安排大批量订单，所以默认每日剩余产能一定大于大批量订单安排的固定产能
                                                    diffDayCap = tempQty - bigOrderCap[cResGroup][processEndDate];
                                                    if (diffDayCap > 0)
                                                    {
                                                        tempQty -= bigOrderCap[cResGroup][processEndDate];   //订单净需求数量抵扣安排的固定产能 
                                                        resCap[cOperationNo][cResGroup][processEndDate] -= bigOrderCap[cResGroup][processEndDate]; //更新endDateDJ这天的剩余产能
                                                        bigOrderCap[cResGroup][processEndDate] = 0;
                                                        processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                                    }
                                                    else
                                                    {
                                                        bigOrderCap[cResGroup][processEndDate] -= tempQty;
                                                        resCap[cOperationNo][cResGroup][processEndDate] -= tempQty; //更新endDateDJ这天的剩余产能
                                                        tempQty = 0;
                                                    }
                                                    count2 = 0;
                                                }
                                                else
                                                {
                                                    processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                                    count2++;
                                                    if (count2 > 30)
                                                    {
                                                        break;
                                                    }
                                                    //if(count2 === 30) return {resCode:"failed",resMsg:`制定主计划失败：${cOperationName}工序资源组30天内无有效产能(检查是否有分配设备)或没有给资源配置日历。`,data:{}};
                                                }
                                            }
                                            else
                                            {
                                                continue;
                                            }
                                        }
                                        //记录钉卷工序的完工日期
                                        mainPlanRes[cPOrderNo].Add("cRgEndDate", processEndDate);
                                    }else
                                    {
                                        if (!mainPlanRes.ContainsKey(cPOrderNo))
                                        {
                                            mainPlanRes.Add(cPOrderNo,new Dictionary<string, string>());
                                        }
                                        // return {resCode:"failed",resMsg:`制定主计划失败：当前资源组无配比${cCombination}`,data:{}};
                                        mainPlanRes[cPOrderNo].Add("cRgBegDate", today);
                                        mainPlanRes[cPOrderNo].Add("cBegProDate", today);
                                        mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                        mainPlanRes[cPOrderNo].Add("cResGroupNo", cResGroup);
                                        mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                        mainPlanRes[cPOrderNo].Add("cRgEndDate", today);
                                        //return {resCode:"failed",resMsg:`制定主计划失败：生产订单${cPOrderNo},没有匹配的设备资源`,data:{}};
                                        // logger.warn(`子销售订单${cPOrderNo},当前资源组无相应配比${cCombination}。`);
                                        continue;
                                    }
                                }else
                                {
                                    throw new Exception("制定主计划失败：资源没配置工序");
                                }
                            }
                            else //其他工序 计算其他工序的开完工日期
                            {
                                if (!mainPlanRes.ContainsKey(cPOrderNo))
                                {
                                    mainPlanRes.Add(cPOrderNo, new Dictionary<string, string>());
                                    mainPlanRes[cPOrderNo].Add("cRgBegDate", startDate);
                                    mainPlanRes[cPOrderNo].Add("cBegProDate", startDate);
                                    mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                    mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                    mainPlanRes[cPOrderNo].Add("cResGroupNo", "");
                                }
                                dTransferTimes += (dTransferTime + 8);
                                if (OpeCalendarObj.ContainsKey(cOperationNo))
                                {
                                    //寻找有效的完工日期
                                    float dayCount = 1;
                                    while (dayCount < (dTransferTimes / 24.0))
                                    {
                                        //其他工序，目前默认按照 流转时间dTransferTime 完成1个订单  后面改成依据产能计算
                                        processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                        float p = 0;
                                        while (!OpeCalendarObj[cOperationNo].ContainsKey(processEndDate))
                                        {
                                            processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                            p++;
                                            if (p > 30)
                                            {
                                                break;
                                            }
                                            //if(p === 30) return {resCode:"failed",resMsg:`制定主计划失败：${cOperationName}工序没有配置日历`,data:{}};
                                        }
                                        dayCount++;
                                    }
                                    dTransferTimes -= (dayCount - 1) * (float)24.0;
                                }else
                                {
                                    break;
                                }
                            }
                        }
                    }
                    //记录订单的完工日期
                    if (mainPlanRes.ContainsKey(cPOrderNo))
                    {
                        mainPlanRes[cPOrderNo].Add("cEndProDate", processEndDate);
                    }
                }

                //第二个循环
                for (int i = 0; i < genSOrders.Count; i++)
                {
                    string cPOrderNo = genSOrders[i]["cPOrderNo"].ToString();
                    string cMatNo = genSOrders[i]["cMatNo"].ToString();
                    string cSpecifucation = "";
                    if (MatDataObj.ContainsKey(cMatNo))
                    {
                        cSpecifucation = MatDataObj[cMatNo]["cSpecifucation"].ToString();
                    }
                    string dNetQty3 = genSOrders[i]["dNetQty3"].ToString();
                    string dRealQty = genSOrders[i]["dRealQty"].ToString();
                    string processEndDate = today; //订单的完工日期 默认是今日
                    string startDate = today;      //订单的开工日期 默认是今日
                    List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr = new List<Dictionary<string, Dictionary<string, DataRow>>>();
                    List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr1 = new List<Dictionary<string, Dictionary<string, DataRow>>>();
                    var childProductArr = getChildProduct(tmpArr, cMatNo, BomObj, RoutingObj, outBom); //找出成品对应的半成品子件，及对应的工序
                    var childProductArr2 = getReworkChildProduct(tmpArr1, cPOrderNo, cMatNo, reworkObj); //找出成品对应的半成品子件，及对应的工序

                    if (dNetQty3 != "")
                    {
                        childProductArr = childProductArr2;
                    }
                    //遍历半成品子件，及对应的工序
                    string childProduct = "";
                    string cOperationNo = "";
                    //遍历半成品子件，及对应的工序  
                    for (int j = 0; j < childProductArr.Count; j++)
                    {
                        foreach (var ret in childProductArr[j].Keys)
                        {
                            childProduct = ret;
                        }

                        float dTransferTimes = 0;
                        foreach (var ret in childProductArr[j][childProduct])
                        {
                            cOperationNo = ret.Key;
                            string cOperationName = ret.Value["cOperationName"].ToString(); //工序名称
                            float dTransferTime = ret.Value["dTransferTime"].ToString() != null ? float.Parse(ret.Value["dTransferTime"].ToString()) : 1; //工序间的流转时间
                            if (cOperationName == null)
                            {
                                continue;
                            }
                            //钉卷工序 计算钉卷工序的开完工日期
                            if (cOperationName.Contains("钉卷"))
                            {
                                string cCombination = ret.Value["cCombination"].ToString(); //配比
                                if(cCombination == null)
                                {
                                    throw new Exception("请在ERP中维护" + cSpecifucation + "规格的BOM数据, 同步ERP数据后再重制定主计划！");
                                }
                                string cResGroup = "RG" + cCombination; //配比对应的资源组
                                //若当前有需要的资源组，则才进行计算，否则返回错误
                                if(resCap.ContainsKey(cOperationNo))
                                {
                                    if (resCap[cOperationNo].ContainsKey(cResGroup))
                                    {
                                        float tempQty = float.Parse(dRealQty);
                                        //获取资源组的最早可开工时间
                                        startDate = CommonMethod.Instance.addDate(today, 1, 1); //默认最早可开工日期是明天
                                        if (resStartDateObj.ContainsKey(cResGroup))
                                        {
                                            startDate = resStartDateObj[cResGroup]; //更新资源组的有效最早可开工日期
                                        }
                                        //若startDate这天有剩余产能，则有效，否则再更新startDate
                                        float count = 0;
                                        while (!resCap[cOperationNo][cResGroup].ContainsKey(startDate) || (resCap[cOperationNo][cResGroup].ContainsKey(startDate) && resCap[cOperationNo][cResGroup][startDate] <= 0))
                                        {
                                            startDate = CommonMethod.Instance.addDate(startDate, 1, 1);
                                            count++;
                                            // if(count === 30) return {resCode:"failed",resMsg:`${cOperationName}工序资源组30天内无有效产能或没有给资源配置日历。`,data:{}};
                                            if (count > 30)
                                            {
                                                if (resCap[cOperationNo][cResGroup].ContainsKey(startDate))
                                                {
                                                    //break;
                                                    //return {resCode:"failed",resMsg:`${cOperationName}工序资源组30天内无有效产能,资源组30天的产能被占用完，等待资源释放后该订单在做主计划。`,data:{}};
                                                }
                                                else
                                                {
                                                    break;
                                                    //return {resCode:"failed",resMsg:`${cOperationName}工序30天内没有配置日历。`,data:{}};
                                                }
                                            }
                                        }
                                        //记录开工日期
                                        if (!mainPlanRes.ContainsKey(cPOrderNo))
                                        {
                                            mainPlanRes.Add(cPOrderNo, new Dictionary<string, string>());
                                        }
                                        mainPlanRes[cPOrderNo].Add("cRgBegDate", "");
                                        mainPlanRes[cPOrderNo].Add("cBegProDate", "");
                                        mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                        mainPlanRes[cPOrderNo].Add("cResGroupNo", cResGroup);
                                        mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                        //扣减产能
                                        float diffDayCap;
                                        processEndDate = startDate;
                                        float count2 = 0;

                                        while (tempQty > 0)
                                        {
                                            if (resCap[cOperationNo][cResGroup].ContainsKey(processEndDate))
                                            {
                                                diffDayCap = tempQty - resCap[cOperationNo][cResGroup][processEndDate];
                                                if (diffDayCap > 0)
                                                {
                                                    tempQty -= resCap[cOperationNo][cResGroup][processEndDate];
                                                    resCap[cOperationNo][cResGroup][processEndDate] = 0;
                                                    processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                                }
                                                else
                                                {
                                                    resCap[cOperationNo][cResGroup][processEndDate] -= tempQty;
                                                    tempQty = 0;
                                                }
                                                count2 = 0;
                                            }
                                            else
                                            {
                                                processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                                count2++;
                                                if (count2 > 30)
                                                {
                                                    break;
                                                }
                                                //if(count2 === 30) return {resCode:"failed",resMsg:"制定主计划失败：",data:{}};
                                            }
                                        }
                                        //记录钉卷工序的完工日期
                                        mainPlanRes[cPOrderNo].Add("cRgEndDate", processEndDate);
                                    }
                                    else
                                    {
                                        if (!mainPlanRes.ContainsKey(cPOrderNo))
                                        {
                                            mainPlanRes.Add(cPOrderNo, new Dictionary<string, string>());
                                        }
                                        // return {resCode:"failed",resMsg:`制定主计划失败：当前资源组无配比${cCombination}`,data:{}};
                                        mainPlanRes[cPOrderNo].Add("cRgBegDate", today);
                                        mainPlanRes[cPOrderNo].Add("cBegProDate", today);
                                        mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                        mainPlanRes[cPOrderNo].Add("cResGroupNo", cResGroup);
                                        mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                        mainPlanRes[cPOrderNo].Add("cRgEndDate", today);
                                        //return {resCode:"failed",resMsg:`制定主计划失败：生产订单${cPOrderNo},没有匹配的设备资源`,data:{}};
                                        // logger.warn(`子销售订单${cPOrderNo},当前资源组无相应配比${cCombination}。`);
                                        continue;
                                    }
                                }
                            }
                            else //其他工序 计算其他工序的开完工日期
                            {
                                if (!mainPlanRes.ContainsKey(cPOrderNo))
                                {
                                    mainPlanRes.Add(cPOrderNo, new Dictionary<string, string>());
                                    mainPlanRes[cPOrderNo].Add("cRgBegDate", startDate);
                                    mainPlanRes[cPOrderNo].Add("cBegProDate", startDate);
                                    mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                                    mainPlanRes[cPOrderNo].Add("dQty", dRealQty);
                                    mainPlanRes[cPOrderNo].Add("cResGroupNo", "");
                                }
                                dTransferTimes += (dTransferTime + 8);
                                if (OpeCalendarObj.ContainsKey(cOperationNo))
                                {
                                    //寻找有效的完工日期
                                    float dayCount = 1;
                                    while (dayCount < (dTransferTimes / 24.0))
                                    {
                                        //其他工序，目前默认按照 流转时间dTransferTime 完成1个订单  后面改成依据产能计算
                                        processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                        float p = 0;
                                        while (!OpeCalendarObj[cOperationNo].ContainsKey(processEndDate))
                                        {
                                            processEndDate = CommonMethod.Instance.addDate(processEndDate, 1, 1);
                                            p++;
                                            if (p > 30)
                                            {
                                                break;
                                            }
                                            //if(p === 30) return {resCode:"failed",resMsg:`制定主计划失败：${cOperationName}工序没有配置日历`,data:{}};
                                        }
                                        dayCount++;
                                    }
                                    dTransferTimes -= (dayCount - 1) * (float)24.0;
                                }else
                                {
                                    break;
                                }
                            }
                        }
                    }
                    //记录订单的完工日期
                    // mainPlanRes[cPOrderNo].cEndProDate = processEndDate;
                    if (mainPlanRes.ContainsKey(cPOrderNo))
                    {
                        mainPlanRes[cPOrderNo].Add("cEndProDate", processEndDate);
                    }
                }

                //第三个循环
                for (int i = 0; i < notPlanSOrders.Count; i++)
                {
                    string cPOrderNo = notPlanSOrders[i]["cPOrderNo"].ToString();
                    string cMatNo = notPlanSOrders[i]["cMatNo"].ToString();
                    string dRealQty = notPlanSOrders[i]["dRealQty"].ToString();
                    string processEndDate = today; //订单的完工日期 默认是今日
                    string startDate = today;      //订单的开工日期 默认是今日
                    if (!mainPlanRes.ContainsKey(cPOrderNo))
                    {
                        mainPlanRes.Add(cPOrderNo,new Dictionary<string, string>());
                    }
                    mainPlanRes[cPOrderNo].Add("cMatNo", cMatNo);
                    mainPlanRes[cPOrderNo].Add("dQty", "0");
                    mainPlanRes[cPOrderNo].Add("cRgBegDate", startDate);
                    mainPlanRes[cPOrderNo].Add("cRgEndDate", processEndDate);
                    mainPlanRes[cPOrderNo].Add("cBegProDate", startDate);
                    mainPlanRes[cPOrderNo].Add("cEndProDate", processEndDate);
                    mainPlanRes[cPOrderNo].Add("cResGroupNo", "");
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return mainPlanRes;
        }

        /**
 * @description 找出成品对应的子件以及对应工序（递归调用）
 * @param {Array} tmpArr 缓存数组
 * @param {Array} cMatNo 成品自制件编号
 * @param {Array} BomObj 制造Bom
 * @param {Array} RoutingObj 工艺路径
 */
        public List<Dictionary<string, Dictionary<string, DataRow>>> getChildProduct(List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr,string cMatNo, 
            Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, DataRow>>>> BomObj,
           Dictionary<string, Dictionary<string, DataRow>> RoutingObj, Dictionary<string, Dictionary<string, DataRow>> outBom)
        {
            try
            {
                if (RoutingObj.ContainsKey(cMatNo))
                {
                    Dictionary<string, Dictionary<string, DataRow>> tmpObj = new Dictionary<string, Dictionary<string, DataRow>>();
                    tmpObj.Add(cMatNo, new Dictionary<string, DataRow>());
                    tmpObj[cMatNo] = RoutingObj[cMatNo]; //RoutingObj[cMatNo] 是个map对象
                    tmpArr.Insert(0, tmpObj);
                }
                else
                {
                    throw new Exception("请在ERP中维护" + cMatNo + "规格的BOM数据,同步ERP数据后再重制定主计划!");
                }

                if(outBom.ContainsKey(cMatNo))
                {
                    string cOperationNo = outBom[cMatNo]["output"]["cOperationNo"].ToString();
                    foreach (var tmp_proNo in BomObj[cMatNo]["input"][cOperationNo].Keys)
                    {
                        string cMatandResType = BomObj[cMatNo]["input"][cOperationNo][tmp_proNo]["cMatandResType"].ToString();
                        if ("自制件" == cMatandResType)
                        {
                            tmpArr = getChildProduct(tmpArr, tmp_proNo, BomObj, RoutingObj, outBom);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return tmpArr;
        }


        private List<Dictionary<string, Dictionary<string, DataRow>>> getReworkChildProduct(List<Dictionary<string, Dictionary<string, DataRow>>> tmpArr, string cSONo, string cMatNo, 
            Dictionary<string, Dictionary<string, List<DataRow>>> reworkObj)
        {
            var RoutingObj = new Dictionary<string, Dictionary<string, DataRow>>();
            var tmpObj = new Dictionary<string, Dictionary<string, DataRow>>();
            try
            {
               if(reworkObj.ContainsKey(cSONo))
                {
                    var cProRoutingNo = reworkObj[cSONo];
                    foreach(var RoutingNo in cProRoutingNo.Keys)
                    {
                        for (int i = 0; i < cProRoutingNo[RoutingNo].Count; i++)
                        {
                            string cOperationNo = cProRoutingNo[RoutingNo][i]["cOperationNo"].ToString();
                            if (!RoutingObj.ContainsKey(cMatNo))
                            {
                                RoutingObj.Add(cMatNo, new Dictionary<string, DataRow>());
                            }
                            RoutingObj[cMatNo].Add(cOperationNo, cProRoutingNo[RoutingNo][i]);
                        }
                        tmpObj.Add(cMatNo, new Dictionary<string, DataRow>());
                        tmpObj[cMatNo] = RoutingObj[cMatNo];
                    }
                }
                tmpArr.Insert(0, tmpObj);
            }
            catch (Exception e)
            {
                throw e;
            }
            return tmpArr;
        }
        #endregion

        //计算总需求

    }
}